import { ElementPropertyConfig } from '@farris/ide-property-panel';
import { EditorTypes } from '@farris/ui-datagrid-editors';
import { FormSchemaEntityFieldTypeName, UniformEditorDataUtil } from '@farris/designer-services';
import { ItemCollectionConverter, ItemCollectionEditorComponent } from '@farris/designer-devkit';
import { FormPropertyChangeObject } from '../../../../../lib/entity/property-change-entity';
import { InputProps } from '../../common/property/input-property-config';
import { EventsEditorFuncUtils } from '../../../../utils/events-editor-func';
import { cloneDeep } from 'lodash-es';
export class EnumFieldProp extends InputProps {

    propertyConfig: ElementPropertyConfig[];


    getPropConfig(propertyData: any): ElementPropertyConfig[] {

        this.propertyConfig = [];

        // 基本信息属性
        const basicPropConfig = this.getBasicPropConfig(propertyData, this.viewModelId);
        this.propertyConfig.push(basicPropConfig);

        // 外观属性
        const appearanceProperties = this.getAppearancePropConfig(propertyData, this.viewModelId);
        this.propertyConfig.push(appearanceProperties);

        // 行为属性
        const behaviorPropConfig = this.getBehaviorPropConfig(propertyData, this.viewModelId);
        this.propertyConfig.push(behaviorPropConfig);

        // 扩展区域属性
        // const appendPropConfig = this.getInputAppendPropertyConfig(propertyData, this.viewModelId);
        // this.propertyConfig.push(appendPropConfig);

        // 事件属性
        const eventPropConfig = this.getSelectEventPropConfig(propertyData, this.viewModelId);
        this.propertyConfig.push(eventPropConfig);

        // 表达式属性
        const exprPropConfig = this.getExpressionPropConfig(propertyData, this.viewModelId);
        if (exprPropConfig) {
            this.propertyConfig.push(exprPropConfig);
        }

        return this.propertyConfig;

    }

    public getBasicPropConfig(propertyData: any, viewModelId: string, showPosition = 'card'): ElementPropertyConfig {

        const basicProperties = this.getBasicCommonPropConfig(propertyData);
        basicProperties.push(
            {
                propertyID: 'controlSource',
                propertyName: '控件来源',
                propertyType: 'select',
                description: '组件的控件来源',
                iterator: [{ key: 'Farris', value: 'Farris' }, { key: 'Kendo', value: 'Kendo' }],
                refreshPanelAfterChanged: true,
                visible: showPosition === 'card' && propertyData.controlSource !== 'Farris'
            }
        );
        const self = this;
        return {
            categoryId: 'basic',
            categoryName: '基本信息',
            properties: basicProperties,
            setPropertyRelates(changeObject: FormPropertyChangeObject, prop, parameters) {

                if (!changeObject) {
                    return;
                }
                switch (changeObject.propertyID) {
                    case 'type': {
                        self.changeControlType(propertyData, changeObject.propertyValue);
                        break;
                    }
                    case 'controlSource': {

                        // 变更【外观分类】下的属性
                        const newAppearancePropConfig = self.getAppearancePropConfig(propertyData, viewModelId);
                        const currentAppearanceConfig = self.propertyConfig.find(cat => cat.categoryId === 'appearance');
                        Object.assign(currentAppearanceConfig, newAppearancePropConfig);

                        // 变更【行为分类】下的属性
                        const newBehaviorPropConfig = self.getBehaviorPropConfig(propertyData, viewModelId);
                        const currentBehaviorConfig = self.propertyConfig.find(cat => cat.categoryId === 'behavior');
                        Object.assign(currentBehaviorConfig, newBehaviorPropConfig);

                        // 变更【事件分类】下的属性
                        const newEventPropConfig = self.getSelectEventPropConfig(propertyData, viewModelId);
                        const currentEventConfig = self.propertyConfig.find(cat => cat.categoryId === 'event');
                        Object.assign(currentEventConfig, newEventPropConfig);


                    }
                }

            },

        };
    }

    private getAppearancePropConfig(propertyData: any, viewModelId: string, showPosition = 'card'): ElementPropertyConfig {

        let appearanceProperties = [];
        if (showPosition === 'card' || showPosition === 'tableTdEditor') {
            const appearanceCommonProps = this.getAppearanceCommonPropConfig(propertyData, viewModelId, showPosition);
            appearanceProperties = appearanceProperties.concat(appearanceCommonProps);
        }


        const self = this;
        const config = {
            categoryId: 'appearance',
            categoryName: '外观',
            properties: appearanceProperties,
            setPropertyRelates(changeObject: FormPropertyChangeObject, prop, parameters) {

                if (!changeObject) {
                    return;
                }
                self.changeAppearancePropertyRelates(this.properties, changeObject, propertyData, parameters);
            },

        };
        if (showPosition !== 'card') {
            Object.assign(config, {
                categoryId: showPosition + '_' + config.categoryId,
                propertyData,
                enableCascade: true,
                parentPropertyID: 'editor',
                tabId: showPosition,
                tabName: '编辑器'
            });
        }
        return config;
    }

    private getBehaviorPropConfig(propertyData: any, viewModelId: string, showPosition = 'card'): ElementPropertyConfig {
        const enumDataConfig = this.getEnumDataConfig(propertyData, viewModelId);
        const { maxLength, bindingFieldType } = this.getMaxLengthOfBindingField(propertyData, viewModelId);
        const controlSource = propertyData.controlSource;

        let behaviorProperties = [];
        if (showPosition === 'card' || showPosition === 'tableTdEditor') {
            behaviorProperties = this.getBehaviorCommonPropConfig(propertyData, viewModelId);
        }


        behaviorProperties.push(
            {
                propertyID: 'dataSourceType',
                propertyName: '数据源类型',
                propertyType: 'select',
                description: '数据源类型选择',
                iterator: [{ key: 'static', value: '静态' }, { key: 'dynamic', value: '动态' }],
                defaultValue: 'static',
                controlSource: 'Farris',
                visible: controlSource === 'Farris' && (showPosition === 'card' || showPosition === 'tableTdEditor')
            },
            {
                propertyID: 'bindDataSource',
                propertyName: '枚举数据',
                propertyType: 'unity',
                description: '枚举数据设置',
                editorParams: {
                    controlName: UniformEditorDataUtil.getControlName(propertyData),
                    editorOptions: {
                        types: ['variable'],
                        variables: UniformEditorDataUtil.getVariables(viewModelId, this.domService),
                        getVariables: () => UniformEditorDataUtil.getVariables(viewModelId, this.domService),
                        newVariableType: 'Array',
                        newVariablePrefix: ''
                    },
                },
                visible: controlSource === 'Farris' && propertyData.dataSourceType === 'dynamic',
                showClearButton: true
            },
            {
                propertyID: 'enumData',
                propertyName: '枚举数据',
                propertyType: 'modal',
                description: '枚举数据设置',
                editor: ItemCollectionEditorComponent,
                converter: new ItemCollectionConverter(),
                ...enumDataConfig.editorConfig,
                visible: propertyData.dataSourceType === 'static' && (showPosition === 'card' || showPosition === 'tableTdEditor')
            },
            {
                propertyID: 'idField',
                propertyName: '枚举值字段',
                propertyType: 'string',
                description: '枚举值字段设置',
                controlSource: 'Farris',
                visible: controlSource === 'Farris' && (showPosition === 'card' || showPosition === 'tableTdEditor'),
                readonly: propertyData.dataSourceType === 'static'
            },
            {
                propertyID: 'textField',
                propertyName: '枚举名称字段',
                propertyType: 'string',
                description: '枚举名称字段设置',
                controlSource: 'Farris',
                visible: controlSource === 'Farris' && (showPosition === 'card' || showPosition === 'tableTdEditor'),
                readonly: propertyData.dataSourceType === 'static'
            },
            {
                propertyID: 'mappingField',
                propertyName: '映射字段',
                propertyType: 'string',
                description: '映射字段设置',
                controlSource: 'Farris',
                visible: controlSource === 'Farris'
            },
            {
                propertyID: 'multiSelect',
                propertyName: '允许多选',
                propertyType: 'boolean',
                description: '是否允许多选',
                controlSource: 'Farris',
                visible: controlSource === 'Farris' && bindingFieldType !== FormSchemaEntityFieldTypeName.Enum
            },
            {
                propertyID: 'uri',
                propertyName: '服务端API',
                propertyType: 'string',
                description: '服务端API设置',
                controlSource: 'Farris',
                visible: controlSource === 'Farris'
            },
            {
                propertyID: 'editable',
                propertyName: '允许编辑',
                propertyType: 'boolean',
                description: '是否允许编辑',
                controlSource: 'Farris',
                visible: controlSource === 'Farris'
            },
            {
                propertyID: 'autoWidth',
                propertyName: '自动宽度',
                propertyType: 'boolean',
                description: '宽度是否自动调整',
                controlSource: 'Farris',
                visible: controlSource === 'Farris'
            },
            {
                propertyID: 'viewType',
                propertyName: '展示类型',
                propertyType: 'select',
                description: '展示类型选择',
                iterator: [{ key: 'text', value: '文本' }, { key: 'tag', value: '标签' }],
                controlSource: 'Farris',
                visible: controlSource === 'Farris' && propertyData.multiSelect &&
                    (showPosition === 'card' || showPosition === 'tableTdEditor')
            },
            {
                propertyID: 'enableCancelSelected',
                propertyName: '重复点击取消选中项',
                propertyType: 'boolean',
                description: '重复点击是否取消选中项',
                controlSource: 'Farris',
                visible: controlSource === 'Farris'
            },
            {
                propertyID: 'noSearch',
                propertyName: '任意输入',
                propertyType: showPosition === 'gridFieldEditor' ? 'boolean' : 'unity',
                description: '是否允许任意输入',
                readonly: bindingFieldType === FormSchemaEntityFieldTypeName.Enum,
                editorParams: {
                    controlName: UniformEditorDataUtil.getControlName(propertyData),
                    constType: 'enum',
                    editorOptions: {
                        types: ['const', 'variable'],
                        enums: [{ key: true, value: 'true' }, { key: false, value: 'false' }],
                        variables: UniformEditorDataUtil.getVariables(viewModelId, this.domService),
                        getVariables: () => UniformEditorDataUtil.getVariables(viewModelId, this.domService),
                        newVariableType: 'Boolean',
                        newVariablePrefix: 'is'
                    }
                }
            },
            {
                propertyID: 'maxSearchLength',
                propertyName: '输入字符的最大长度',
                propertyType: 'number',
                description: '输入字符的最大长度设置',
                decimals: 0,
                min: 0,
                max: maxLength,
                visible: propertyData.noSearch
            },
            {
                propertyID: 'enableClear',
                propertyName: '启用清除按钮',
                propertyType: 'boolean',
                description: '是否启用清除按钮',
                controlSource: 'Farris',
                visible: controlSource === 'Farris'
            }
        );

        const self = this;
        const config = {
            categoryId: 'behavior',
            categoryName: '行为',
            properties: behaviorProperties,
            setPropertyRelates(changeObject: FormPropertyChangeObject, data, parameters) {
                self.changeBehaviorPropertyRelates(this.properties, changeObject, propertyData, parameters, showPosition);

                if (!changeObject) {
                    return;
                }
                switch (changeObject && changeObject.propertyID) {
                    case 'multiSelect': {
                        this.properties.map(p => {
                            if (p.propertyID === 'viewType') {
                                p.visible = controlSource === 'Farris' && changeObject.propertyValue && showPosition === 'card';
                            }
                        });
                        break;
                    }
                    case 'enumData': {
                        if (enumDataConfig.dynamicMappingKeys && parameters) {
                            propertyData.idField = parameters.valueField;
                            propertyData.textField = parameters.nameField;
                        }
                        changeObject.relateChangeProps = [{
                            propertyID: 'idField',
                            propertyValue: propertyData.idField
                        },
                        {
                            propertyID: 'textField',
                            propertyValue: propertyData.textField
                        }];
                        break;
                    }
                    case 'dataSourceType': {
                        const enumData = this.properties.find(p => p.propertyID === 'enumData');
                        const bindDataSource = this.properties.find(p => p.propertyID === 'bindDataSource');
                        const idField = this.properties.find(p => p.propertyID === 'idField');
                        const textField = this.properties.find(p => p.propertyID === 'textField');

                        if (enumData) {
                            enumData.visible = changeObject.propertyValue === 'static' && showPosition === 'card';
                        }

                        if (bindDataSource) {
                            bindDataSource.visible = changeObject.propertyValue === 'dynamic';
                        }
                        if (idField) {
                            idField.readonly = changeObject.propertyValue === 'static';
                        }
                        if (textField) {
                            textField.readonly = changeObject.propertyValue === 'static';
                        }

                        break;
                    }
                    case 'noSearch': {
                        const maxSearchLength = this.properties.find(p => p.propertyID === 'maxSearchLength');
                        if (maxSearchLength) {
                            maxSearchLength.visible = changeObject.propertyValue;
                        }
                        break;
                    }
                }
            }

        };
        if (showPosition !== 'card') {
            Object.assign(config, {
                categoryId: showPosition + '_' + config.categoryId,
                propertyData,
                enableCascade: true,
                parentPropertyID: 'editor',
                tabId: showPosition,
                tabName: '编辑器'
            });
        }
        return config;
    }


    /**
     * 事件属性
     */
    private getSelectEventPropConfig(propertyData: any, viewModelId: string, showPosition = 'card'): ElementPropertyConfig {
        return this.getEventPropertyConfig(propertyData, viewModelId, showPosition);
    }

    switchEvents(propertyData, eventList) {
        eventList = super.switchEvents(propertyData, eventList);
        const events = [
            {
                label: 'beforeShow',
                name: '面板显示前事件'
            },
            {
                label: 'beforeHide',
                name: '面板隐藏前事件'
            },
            {
                label: 'onShown',
                name: '面板打开事件'
            },
            {
                label: 'onHidden',
                name: '面板关闭事件'
            },
            {
                label: 'valueChanged',
                name: '值变化事件'
            }
        ];
        if (propertyData.controlSource === 'Farris') {
            const eventListExist = eventList.find(eventListItem => eventListItem.label === 'beforeShow');
            if (!eventListExist) {
                events.forEach(event => { eventList.push(cloneDeep(event)); });
            }
        } else {
            events.forEach(event => {
                eventList = eventList.filter(eventListItem => eventListItem.label !== event.label);
            });
        }

        if (propertyData.enableClear) {
            const onClear = eventList.find(eventListItem => eventListItem.label === 'onClear');
            if (!onClear) {
                eventList.push({
                    label: 'onClear',
                    name: '清除事件'
                });
            }
        } else {
            eventList = eventList.filter(eventListItem => eventListItem.label !== 'onClear');
        }

        return eventList;
    }


    /**
     * 列编辑器属性
     * @param gridFieldData 列数据
     */
    getGridFieldEdtiorPropConfig(gridFieldData: any, viewModelId: string) {
        const propertyData = gridFieldData.editor;

        this.propertyConfig = [];

        // 编辑器类型属性
        const editorTypeConfig = this.getGridFieldEditorTypePropertyConfig(gridFieldData, viewModelId);
        if (editorTypeConfig) {
            this.propertyConfig.push(editorTypeConfig);
        }

        // 行为属性
        const behaviorConfig = this.getBehaviorPropConfig(propertyData, viewModelId, 'gridFieldEditor');
        this.appendBehaviorPropsForGridFieldEditor(behaviorConfig, propertyData, viewModelId);
        this.propertyConfig.push(behaviorConfig);

        // 事件属性
        const eventConfig = this.getSelectEventPropConfig(propertyData, viewModelId, 'gridFieldEditor');
        this.propertyConfig.push(eventConfig);

        return this.propertyConfig;
    }


    /**
     * 枚举数据的编辑器不同：
     * kendo的控件确定只有value-name键值
     * farris的控件若绑定了枚举字段只有value-name 键值；若绑定了变量或者字符串字段则可以自行指定idField 和textField
     */
    getEnumDataConfig(propertyData: any, viewModelId: string): { editorConfig: any, dynamicMappingKeys: boolean } {
        if (!propertyData.binding) {
            return { editorConfig: null, dynamicMappingKeys: false };
        }

        const editorConfig: any = {
            editorParams: {
                columns: [
                    { field: 'value', title: '枚举值', editor: { type: EditorTypes.TEXTBOX } },
                    { field: 'name', title: '枚举名称', editor: { type: EditorTypes.TEXTBOX } },
                ],
                requiredFields: ['value', 'name'],
                uniqueFields: ['value', 'name'],
                modalTitle: '枚举编辑器',
                canEmpty: true
            }
        };
        if (propertyData.controlSource !== 'Farris') {
            return { editorConfig, dynamicMappingKeys: false };
        }
        // 绑定枚举字段的 下拉控件，编辑器只支持value-name
        if (propertyData.binding.type === 'Form') {
            const dgVM = this.dgVMService.getDgViewModel(viewModelId);
            const dgVMField = dgVM.fields.find(f => f.id === propertyData.binding.field);
            if (dgVMField.type.name === 'Enum') {
                return { editorConfig, dynamicMappingKeys: false };
            }
        }
        editorConfig.editorParams.dynamicMappingKeys = true;
        editorConfig.editorParams.valueField = propertyData.idField;
        editorConfig.editorParams.nameField = propertyData.textField;

        return { editorConfig, dynamicMappingKeys: true };
    }
    /**
     * 获取绑定字段schema中的长度、类型属性
     */
    private getMaxLengthOfBindingField(propertyData: any, viewModelId: string) {
        let maxLength;
        let bindingFieldType;
        if (propertyData.binding && propertyData.binding.type === 'Form') {
            const fieldInfo = this.schemaService.getFieldByIDAndVMID(propertyData.binding.field, viewModelId);
            if (fieldInfo && fieldInfo.schemaField) {
                maxLength = fieldInfo.schemaField.type.length;
                bindingFieldType = fieldInfo.schemaField.type.name;
            }
        }
        return { maxLength, bindingFieldType };
    }


    /**
     * table单元格编辑器属性
     * @param tdData 单元格数据
     * @param viewModelId viewModelId
     * @returns 属性配置
     */
    getTableTdEdtiorPropConfig(tdData: any, viewModelId: string): ElementPropertyConfig[] {
        const propertyData = tdData.editor;

        this.propertyConfig = [];

        // 外观属性
        const appearanceConfig = this.getAppearancePropConfig(propertyData, viewModelId, 'tableTdEditor');
        this.propertyConfig.push(appearanceConfig);

        // 行为属性
        const behaviorConfig = this.getBehaviorPropConfig(propertyData, viewModelId, 'tableTdEditor');
        behaviorConfig.properties = behaviorConfig.properties.filter(p => !'binding,visible'.includes(p.propertyID));
        this.propertyConfig.push(behaviorConfig);

        // 扩展区域属性
        const appendPropConfig = this.getInputAppendPropertyConfig(propertyData, viewModelId, 'tableTdEditor');
        this.propertyConfig.push(appendPropConfig);

        // 事件属性
        const eventConfig = this.getSelectEventPropConfig(propertyData, viewModelId, 'tableTdEditor');
        this.propertyConfig.push(eventConfig);


        // 表达式属性
        const exprPropConfig = this.getExpressionPropConfig(propertyData, viewModelId, 'tableTdEditor');
        if (exprPropConfig) {
            this.propertyConfig.push(exprPropConfig);
        }

        return this.propertyConfig;
    }

}
